package com.barbarosso.utils.loader {
	import nl.demonsters.debugger.MonsterDebugger;
	
	import com.barbarosso.utils.loader.types.AbstractAsset;
	
	import flash.errors.IllegalOperationError;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;		

	/**
	 * @author barbarosso
	 */
	public class AssetLoader implements IEventDispatcher {

		private var _eventDispatcher : EventDispatcher ;
		private var _assetCollection : AssetCollection;
		private var _currentAsset : AbstractAsset;

		private var _currentAssetIndex : int = 0;

		private var _isLoadAllAssets : Boolean ;

		public function AssetLoader( p_assetCollection : AssetCollection , p_isLoadAllAssets : Boolean = false) {
			_eventDispatcher = new EventDispatcher();
			
			if(p_assetCollection) {
				_assetCollection = p_assetCollection;
				MonsterDebugger.trace(this, p_assetCollection);
				if(p_isLoadAllAssets){
					_currentAsset = _assetCollection.getItemByIndex(_currentAssetIndex) as AbstractAsset;
					_isLoadAllAssets = p_isLoadAllAssets;
					loadAsset();
				}
			}
		}

		/*
		 * setters and getters methods ----------------------------------------------
		 */
		 
		/*
		 * read only properties
		 */
		public function get assetCollection(  ) : AssetCollection {
			return _assetCollection  ;
		} 

		/*
		 * protected methods ----------------------------------------------
		 */

		protected function loadAsset() : void {
			MonsterDebugger.trace(this, "_currentAsset = " + _currentAsset.id);
			if(!_currentAsset.isLoaded){
				_currentAsset.addEventListener(AssetEvent.COMPLETE, assetLoadedHandler);
				_currentAsset.load();
			}else{
				nextAsset();
			}
		}

		protected function assetLoadedHandler( event : AssetEvent) : void {
			MonsterDebugger.trace(this, "assetLoadedHandler ----------------------------------");
			if(_isLoadAllAssets) {
				MonsterDebugger.trace(this, "assetLoadedHandler: load all assets");
				nextAsset();
			}else{
				MonsterDebugger.trace(this, "assetLoadedHandler: not load all assets");
			}
		}

		protected function nextAsset() : void {
			var n : int = _assetCollection.length;
			_currentAsset = null;
			for (var i:int = 0; i < n; i++)
			{
			    var asset : AbstractAsset = _assetCollection.getItemByIndex(i) as AbstractAsset;
			    if(!asset.isLoaded){
					_currentAssetIndex = i;
					_currentAsset = _assetCollection.getItemByIndex(_currentAssetIndex) as AbstractAsset;
					break;
				}
			}
			
			
			if(_currentAsset) {
				loadAsset();
			} else {
				loadingAssetsCompletedHandler();
			}
		}
		
		protected function cancelAsset() : void {
			if(_currentAsset){
				_currentAsset.removeEventListener(AssetEvent.COMPLETE, assetLoadedHandler);
				_currentAsset.cancel();
				_currentAsset = null;
			}		
		}
		
		protected function loadingAssetsCompletedHandler() : void{
			MonsterDebugger.trace(this, "loading completed ---------------------------------------");
			var n : int = _assetCollection.length;
			for (var i:int = 0; i < n; i++)
			{
				var asset : AbstractAsset = _assetCollection.getItemByIndex(i) as AbstractAsset;
				MonsterDebugger.trace(this, asset.id + " his status is " + asset.isLoaded);
			}
			var event : AssetEvent = new AssetEvent(AssetEvent.COMPLETE);
			dispatchEvent(event);
		}

		/*
		 * public methods ----------------------------------------------
		 */
		 
		/*
		 * 
		 */
		public function addAsset( p_asset : AbstractAsset , p_autoLoad : Boolean = false) : void {
			if(p_asset) {
				_assetCollection.addAsset(p_asset);
				if(p_autoLoad) {
					cancelAsset();
					_currentAsset = _assetCollection.getLastItem() as AbstractAsset;
					MonsterDebugger.trace(this, "addAsset " + _currentAsset.id + p_asset.id + " assetcollection length = " + _assetCollection.length);
					loadAsset();
				}
			} else {
				throw IllegalOperationError("there's no Asset passed");	
			}
		}

		public function loadAssets() : Boolean {
			_isLoadAllAssets = true;
			return false;
		}

		public function loadAssetById( assetId : String ) : Boolean {
			if(_currentAsset) {
				cancelAsset();
			}
			_currentAsset = _assetCollection.getItemByChildProperty("id", assetId) as AbstractAsset;
			if(_assetCollection){
				loadAsset();
				return true;
			}
			 
			return false;
		}

		public function dispatchEvent(event : Event) : Boolean {
			return _eventDispatcher.dispatchEvent(event);
		}

		public function hasEventListener(type : String) : Boolean {
			return _eventDispatcher.hasEventListener(type);
		}

		public function willTrigger(type : String) : Boolean {
			return _eventDispatcher.willTrigger(type);
		}

		public function removeEventListener(type : String, listener : Function, useCapture : Boolean = false) : void {
			_eventDispatcher.removeEventListener(type, listener);
		}

		public function addEventListener(type : String, listener : Function, useCapture : Boolean = false, priority : int = 0, useWeakReference : Boolean = false) : void {
			_eventDispatcher.addEventListener(type, listener);
		}
	}
}
